package jiguang

import (
	"GOPAAS/internal/utils"
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"encoding/pem"
	"errors"
	"fmt"
	"log"
	"strconv"
)

const REQUEST_URL = "https://api.verification.jpush.cn/v1/web/loginTokenVerify"
const REQUEST_URL_H5 = "https://api.verification.jpush.cn/v1/web/h5/loginTokenVerify"

const PUSH_URL_V3 = "https://api.jpush.cn/v3/push"
const PUSH_CID_URL_V3 = "https://api.jpush.cn/v3/push/cid"
const PUSH_CHECK_URL_V3 = "https://api.jpush.cn/v3/push/validate"

type Jiguang struct {
	AppKey       string
	MasterSecret string
}

func New(app_key string, master_secret string) Jiguang {
	return Jiguang{
		app_key, master_secret,
	}
}

type PhoneRes struct {
	Id      int64  `json:"id"`
	Code    int64  `json:"code"`
	Content string `json:"content"`
	ExID    string `json:"exID"`
	Phone   string `json:"phone"`
}

// GetPhone 获取一键登录手机号码
func (j *Jiguang) GetPhone(loginToken string, client_type string) (phone string, err error) {
	var url string
	if client_type == "app" {
		url = REQUEST_URL
	} else {
		url = REQUEST_URL_H5
	}
	body, err := utils.HttpPost(url, map[string]string{"Authorization": j.GetAuthToken(), "Content-Type": "application/json;charset=UTF-8"}, nil, map[string]string{"loginToken": loginToken})
	if err != nil {
		return
	}
	var res PhoneRes
	err = json.Unmarshal(body, &res)
	if res.Code != 8000 {
		err = errors.New(res.Content)
		return
	}
	//a := "4ejFYW3QaE2HBMWPXh7+jwBdgLQsBdvGF4oaD7YDPaprbHsv/M8ps/s8pytxWmcS1f5/nuQ4eOsRMIYgXT5+6ZnHtJ8dA3E58Z8QAna7PcR/eUlGcCKhzzKWzP8C99nBQUJVu/43OTAnLlihn6rIUEePKL6IHiAEDsIDedR/0Ug="
	//phone, err = j.decrypt(a)
	phone, err = j.decrypt(res.Phone)
	return
}

// PushV3 推送消息
func (j *Jiguang) PushV3(data map[string]interface{}) (body []byte, err error) {
	body, err = utils.HttpPostJson(PUSH_URL_V3, map[string]string{"Authorization": j.GetAuthToken(), "Content-Type": "application/json;charset=UTF-8"}, nil, data)
	if err != nil {
		return
	}
	return
}

// GetCid 获取防止重复cid
func (j *Jiguang) GetCid(n int) (body []byte, err error) {
	body, err = utils.HttpGet(PUSH_CID_URL_V3, map[string]string{"count": strconv.Itoa(n)}, map[string]string{"Authorization": j.GetAuthToken()})
	if err != nil {
		return
	}
	return
}
func (j *Jiguang) GetAuthToken() string {
	str := "Basic " + utils.Base64([]byte(j.AppKey+":"+j.MasterSecret))
	fmt.Println(str)
	return str
}

// 解密
func (j *Jiguang) decrypt(encrypted string) (result string, err error) {
	PREFIX := "-----BEGIN RSA PRIVATE KEY-----"
	SUFFIX := "-----END RSA PRIVATE KEY-----"
	prikey := "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJSgwSRE8r09bknm\n9+/76lchBdC2iGu5LiO/6vLrQ+YI0m7F7Xzkk9/yMqy+rSlVHLfYjdbyxc00JhKb\nnQbnU6gDVguEoPdXfOLsmGHabUnisXQmOkOOmGODHod8hSDDF4L03bdJNb+Mzh0U\nD0ZH5qewJqxAV51ZufRHiEOAWQPpAgMBAAECgYEAkcN+6KU+M15WFeCRdSlpUH4w\nh9scvBlnKOSF9ivJ8YbhaoZvPbenV1DfZg+zIAA7JAscQJzkZTYpyMIZJLYmkffi\nTCPl327mrKvpXxsXwxr7vrvee0QtTjsubPHEmBj2QEabrleHj5FLhzdIyTvyQbLz\nvgdmn5bICVGyQNst1ekCQQDFG1Ngs3gFhxwRMaTqdPly8YxVTy5powJFZo1toQWI\nzTUCOe5cu8ch8A3gXIcXrOMl1EZriHW4K4pGRDRZefinAkEAwQlKcv07jyVLiN/d\nB7Z9wGSZ/7Bu4rInbj6JRK25RdjtzdJTZ/C0pe4f4yOdEUnDwT2wxRcC3u9d2Z0D\nHBMg7wJBAKDrc0HSo91XdhmvfyWPRIyMGfcYAxtpYxRH6pUjTgJnDqz3oNwCzkut\n0ZZn1D8G/hfHW4q1SO6IVYaSbm7SfqcCQGJMdeH6fELXrhBEV0zfLEg1sooW8VB1\ngkjMhaA4ivk7j1VZPmnWlFdO3GQRNaGhG5Mi9ApZPngCEpuHLhc00ncCQDHW3HiO\nur+1mOE1CpZkKf6xrmsYTmU3fscZNaMJ4jisKPr1zmHPiYEbzYUWB2nj3xgPD1nx\nB/sKUTgGlWu1m64="

	encryptedB, err := base64.StdEncoding.DecodeString(encrypted)
	if err != nil {
		log.Println("invalid encrypted")
		return
	}
	key := PREFIX + "\n" + prikey + "\n" + SUFFIX
	res, err := RsaDecrypt(encryptedB, []byte(key))
	if err != nil {
		log.Println("err:", err)
		return
	}
	log.Println("result:", string(res))
	result = string(res)
	return
}

// RsaDecrypt 私钥解密
func RsaDecrypt(encrypted, prikey []byte) ([]byte, error) {
	var data []byte
	block, _ := pem.Decode(prikey)
	if block == nil {
		return data, errors.New("private key error")
	}
	rsaKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return data, err
	}
	//rsa, err := ssh.ParseRawPrivateKey(rsaKey)
	key, ok := rsaKey.(*rsa.PrivateKey)
	if !ok {
		return data, errors.New("invalid private key")
	}
	data, err = rsa.DecryptPKCS1v15(rand.Reader, key, encrypted)
	return data, err
}
